package com.wzz.common.rsa;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**
 * 牛帅
 * <p>
 * Title: RSACrypto
 * </p>
 * <p>
 * Description: 實現RSA算法在Java和Objective C之間的加密解密 1. 導入Objective C
 * 調用SSCrypto生成的RSA公鑰文件，或字符串，生成公鑰 2. 用公鑰加密文本，生成密文字節，返回給Objective C，用其私鑰解密
 * 
 * 3. 生成RSA公鑰和私鑰對，將公鑰和私鑰存為二進制文件或SSCrypto可接受的文本，傳給Objective C加密 4.
 * 讀取本地私鑰，解密Objective C傳回的密文字節
 * </p>
 * 用的方法只要把这个包都考进去即可
 * 调用RSA的方法 一般服务器进行加密 然后需要我们去解密
 * 1. RSACrypto.decrypt(Util.hex2byte(url.getBytes("UTF-8")), Constant.PRIVATE_KEY)
 *    hex2byte(url.getBytes("UTF-8")), Constant.PRIVATE_KEY) 方法是先要装换下字符串
 *    PRIVATE_KEY 是私钥
 *    decrypt(a,b) 然后进行解密 解密出来的东西就是我们想要的
 *    如果打印的有问题 需要过滤下 
 *    tring tempaudioUrl = audioUrl.substring(audioUrl.indexOf("http"));
 *    tempaudioUrl 就是我们想要的 解密出来的string
 */

public class RSACrypto {
  // 加密算法 文本處理模式 文本填充模式
  // private final static String RSA = "RSA/ECB/PKCS1Padding";
  private final static String RSA = "RSA";
  // 公鑰
  public static RSAPublicKey uk;
  // 私鑰
  public static RSAPrivateKey rk;

  // 是否保存key及保存為何種格式
  public final static int KEY_SAVE_NONE = -1;
  public final static int KEY_SAVE_BIN = 1;
  public final static int KEY_SAVE_PEM = 2;

  // PEM文件起止字符串
  public final static String PUBLIC_KEY_BEGIN = "-----BEGIN PUBLIC KEY-----";
  public final static String PUBLIC_KEY_END = "-----END PUBLIC KEY-----";
  public final static String PRIVATE_KEY_BEGIN = "-----BEGIN RSA PRIVATE KEY-----";
  public final static String PRIVATE_KEY_END = "-----END RSA PRIVATE KEY-----";
  // PEM文件行長度
  public final static int PEM_LINE_LENGTH = 64;

  // 二進制公鑰私鑰文件名
  public final static String PRIVATE_BIN_FILE = "C:\\java_private.bin";
  public final static String PUBLIC_BIN_FILE = "C:\\java_public.bin";

  // PEM公鑰私鑰文件名
  public final static String PRIVATE_PEM_FILE = "C:\\java_private.pem";
  public final static String PUBLIC_PEM_FILE = "C:\\java_public.pem";

  // 初始化，可在此加入一些新的算法的Provider，我們僅使用Java提供的標準算法
  public static void init() {
    // Security.addProvider(new BouncyCastleProvider());
  }

  // 生成RSA公鑰和密鑰對
  public static void generateKey(int keySize, int intSaveKey) throws Exception {
    // KeySize 512,1024,2048 建議2048
    if ((keySize != 512) && (keySize != 1024) && (keySize != 2048)) {
      keySize = 2048;
    }

    //
    KeyPairGenerator gen = KeyPairGenerator.getInstance(RSA);
    gen.initialize(keySize, new SecureRandom());
    KeyPair keyPair = gen.generateKeyPair();

    uk = (RSAPublicKey) keyPair.getPublic();
    System.out.println("Generate Public Key:");
    System.out.println(getPublicKeyString(uk));

    rk = (RSAPrivateKey) keyPair.getPrivate();
    System.out.println("Generate Private Key:");
    System.out.println(getPrivateKeyString(rk));

    // Write public and private key to bin file.
    if (intSaveKey == KEY_SAVE_BIN) {
      writeKey(uk, PUBLIC_BIN_FILE);
      writeKey(rk, PRIVATE_BIN_FILE);
    }

    // Write public and private key to pem file.
    if (intSaveKey == KEY_SAVE_PEM) {
      savePublicKeyPEM(uk, PUBLIC_PEM_FILE);
      savePrivateKeyPEM(rk, PRIVATE_PEM_FILE);
    }
  }

  // 從二進制文件加載公鑰私鑰
  public static void loadKeyFromBinFiles() throws Exception {
    uk = (RSAPublicKey) loadPublicKey(new File(PUBLIC_BIN_FILE));
    System.out.println("Load Public Key:");
    System.out.println(getPublicKeyString(uk));

    rk = (RSAPrivateKey) loadPrivateKey(new File(PRIVATE_BIN_FILE));
    System.out.println("Load Private Key:");
    System.out.println(getPrivateKeyString(rk));
  }

  // 從PEM文件加載公鑰私鑰
  public static void loadKeyFromPEMFiles() throws Exception {
    uk = (RSAPublicKey) loadPublicKeyFromPEM(PUBLIC_PEM_FILE);
    System.out.println("Load Public Key from PEM:");
    System.out.println(getPublicKeyString(uk));

    rk = (RSAPrivateKey) loadPrivateKeyFromPEM(PRIVATE_PEM_FILE);
    System.out.println("Load Private Key from PEM:");
    System.out.println(getPrivateKeyString(rk));
  }

  // 保存公鑰為SSCrypto可接受的pem文件格式
  public static void savePublicKeyPEM(RSAPublicKey pubKey, String strPEMKeyFile) {
    String strKey = Util.replaceNewLine(getPublicKeyString(pubKey));
    try {
      FileWriter keyFile = new FileWriter(strPEMKeyFile);
      PrintWriter out = new PrintWriter(keyFile);

      // Write text to file
      out.println(PUBLIC_KEY_BEGIN);
      int keyLength = strKey.length();
      int lines = keyLength / 64;
      for (int i = 0; i < lines; i++) {
        out.println(strKey.substring(i * PEM_LINE_LENGTH, i * PEM_LINE_LENGTH + PEM_LINE_LENGTH));
      }
      out.println(strKey.substring(lines * PEM_LINE_LENGTH, keyLength));
      out.println(PUBLIC_KEY_END);
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  // 保存私鑰為SSCrypto可接受的pem文件格式
  public static void savePrivateKeyPEM(RSAPrivateKey privateKey, String strPEMKeyFile) {
    String strKey = Util.replaceNewLine(getPrivateKeyString(privateKey));

    try {
      FileWriter keyFile = new FileWriter(strPEMKeyFile);
      PrintWriter out = new PrintWriter(keyFile);

      // Write text to file
      out.println(PRIVATE_KEY_BEGIN);
      int keyLength = strKey.length();
      int lines = keyLength / PEM_LINE_LENGTH;
      for (int i = 0; i < lines; i++) {
        out.println(strKey.substring(i * PEM_LINE_LENGTH, i * PEM_LINE_LENGTH + PEM_LINE_LENGTH));
      }
      out.println(strKey.substring(lines * PEM_LINE_LENGTH, keyLength));
      out.println(PRIVATE_KEY_END);
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  // 從二進制文件加載公鑰
  public static PublicKey loadPublicKey(File publicKeyFile) throws GeneralSecurityException, IOException {
    // read public key
    byte[] encodeKey = new byte[(int) publicKeyFile.length()];
    new FileInputStream(publicKeyFile).read(encodeKey);

    EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encodeKey);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    return keyFactory.generatePublic(pubKeySpec);
  }

  // 從二進制文件加載私鑰
  public static PrivateKey loadPrivateKey(File privateKeyFile) throws GeneralSecurityException, IOException {

    // read private key
    byte[] encodedKey = new byte[(int) privateKeyFile.length()];
    new FileInputStream(privateKeyFile).read(encodedKey);

    // create private key
    PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey);
    KeyFactory kf = KeyFactory.getInstance("RSA");

    return kf.generatePrivate(privateKeySpec);
  }

  // 公鑰加密
  private static byte[] encrypt(String text, PublicKey pubRSA) throws Exception {
    Cipher cipher = Cipher.getInstance(RSA);// new BouncyCastleProvider());
    cipher.init(Cipher.ENCRYPT_MODE, pubRSA);
    return cipher.doFinal(text.getBytes());
  }

  // 加密明文文本
  public final static String encrypt(String text) {
    try {
      return Util.byte2hex(encrypt(text, uk));
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  // 解密密文文本
  public final static String decrypt(String data) {
    try {
      return new String(decrypt(Util.hex2byte(data.getBytes())));
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  // 私鑰解密
  private static byte[] decrypt(byte[] src) throws Exception {
    Cipher cipher = Cipher.getInstance(RSA);
    cipher.init(Cipher.DECRYPT_MODE, rk);
    return cipher.doFinal(src);
  }

  // 私鑰解密
  public static String decrypt(byte[] src, PrivateKey privateKey) throws Exception {
    Cipher cipher = Cipher.getInstance(RSA);
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    return new String(cipher.doFinal(src), "utf-8");
  }

  // 取得公鑰字串
  public static String getPublicKeyString(PublicKey publicKey) {

    try {
      return Base64.encodeString(publicKey.getEncoded());
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  // 取得私鑰字串
  public static String getPrivateKeyString(PrivateKey privateKey) {
    try {
      return Base64.encodeString(privateKey.getEncoded());
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
    // return new BASE64Encoder().encode(privateKey.getEncoded());
  }

  // 從Objective C提供的公鑰字串生成公鑰
  public static PublicKey getPublicKeyFromString(String key) throws Exception {
    PublicKey publicKey = null;
    try {
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(Base64.decode(key));
      // new BASE64Decoder().decodeBuffer(key));
      publicKey = keyFactory.generatePublic(publicKeySpec);

    } catch (Exception e) {
      e.printStackTrace();
    }
    return publicKey;
  }

  // 從Objective C提供的公鑰字串生成私鑰
  public static PrivateKey getPrivateKeyFromString(String key){
    PrivateKey privateKey = null;
    try {
      KeyFactory keyFactory = KeyFactory.getInstance("RSA");

      // create private key
      PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(Base64.decode(key));
      // new BASE64Decoder().decodeBuffer(key));

      privateKey = keyFactory.generatePrivate(privateKeySpec);
    } catch (Exception e) {
      e.printStackTrace();
    }

    return privateKey;
  }

  // 從PEM文件加載公鑰
  public static PublicKey loadPublicKeyFromPEM(String strPublicKeyFile) throws Exception {
    // read public key file
    FileInputStream fstream = new FileInputStream(strPublicKeyFile);
    // Get the object of DataInputStream
    DataInputStream in = new DataInputStream(fstream);
    BufferedReader br = new BufferedReader(new InputStreamReader(in));

    String strResult = "";
    String strLine;
    // Read File Line By Line
    while ((strLine = br.readLine()) != null) {
      // Print the content on the console
      System.out.println(strLine);
      if ((strLine.equalsIgnoreCase(PUBLIC_KEY_BEGIN) == false) && (strLine.equalsIgnoreCase(PUBLIC_KEY_END) == false)) {
        strResult += strLine;
      }
    }
    // Close the input stream
    in.close();

    return getPublicKeyFromString(strResult);
  }

  // 從PEM文件加載私鑰
  public static PrivateKey loadPrivateKeyFromPEM(String strPrivateKeyFile) throws Exception {

    // read private key file
    FileInputStream fstream = new FileInputStream(strPrivateKeyFile);
    // Get the object of DataInputStream
    DataInputStream in = new DataInputStream(fstream);
    BufferedReader br = new BufferedReader(new InputStreamReader(in));

    String strResult = "";
    String strLine;
    // Read File Line By Line
    while ((strLine = br.readLine()) != null) {
      // Print the content on the console
      System.out.println(strLine);
      if ((strLine.equalsIgnoreCase(PRIVATE_KEY_BEGIN) == false)
          && (strLine.equalsIgnoreCase(PRIVATE_KEY_END) == false)) {
        strResult += strLine;
      }
    }
    // Close the input stream
    in.close();

    return getPrivateKeyFromString(strResult);
  }

  /**
   * Writes <code>key</code> to file with name <code>filename</code> in standard
   * encoding (X.509 for RSA public key, PKCS#8 for RSA private key).
   * 
   * @param key
   *          the key to write.
   * @param filename
   *          the name of the file.
   * 
   * @throws IOException
   *           if something goes wrong.
   */
  public static void writeKey(Key key, String filename) throws IOException {
    FileOutputStream file = new FileOutputStream(filename);
    file.write(key.getEncoded());
    file.close();
  }
  //
  // // 此方法用于測試生成公鑰私鑰并保存成二進制文件，加密解密
  // public static void testGenerateAndSaveKey() throws Exception {
  // System.out.println("測試生成公鑰私鑰并保存成二進制文件");
  // RSACrypto.generateKey(2048, KEY_SAVE_BIN);
  //
  // for (int i = 0; i < Util.TEST_STRING.length; i++) {
  // String cipherText = RSACrypto.encrypt(Util.TEST_STRING[i]);
  // System.out.println("密文：");
  // System.out.println(cipherText);
  // String plainText = RSACrypto.decrypt(cipherText);
  // System.out.println("明文：");
  // System.out.println(plainText);
  // }
  // }
  //
  // // 此方法用于測試讀取二進制文件生成公鑰私鑰，加密解密
  // public static void testLoadKey() throws Exception {
  // System.out.println("測試從二進制文件加載公鑰私鑰");
  // RSACrypto.loadKeyFromBinFiles();
  //
  // for (int i = 0; i < Util.TEST_STRING.length; i++) {
  // String cipherText = RSACrypto.encrypt(Util.TEST_STRING[i]);
  // System.out.println("密文：");
  // System.out.println(cipherText);
  // String plainText = RSACrypto.decrypt(cipherText);
  // System.out.println("明文：");
  // System.out.println(plainText);
  // }
  // }
  //
  // // 此方法用于測試生成公鑰私鑰并保存成PEM文件，加密解密
  // public static void testGenerateAndSavePEM() throws Exception {
  // System.out.println("測試生成公鑰私鑰并保存成PEM文件");
  // RSACrypto.generateKey(2048, KEY_SAVE_PEM);
  //
  // for (int i = 0; i < Util.TEST_STRING.length; i++) {
  // String cipherText = RSACrypto.encrypt(Util.TEST_STRING[i]);
  // System.out.println("密文：");
  // System.out.println(cipherText);
  // String plainText = RSACrypto.decrypt(cipherText);
  // System.out.println("明文：");
  // System.out.println(plainText);
  // }
  // }
  //
  // // 此方法用于測試讀取PEM文件生成公鑰私鑰，加密解密
  // public static void testLoadPEM() throws Exception {
  // System.out.println("測試從PEM文件加載公鑰私鑰");
  // RSACrypto.loadKeyFromPEMFiles();
  //
  // for (int i = 0; i < Util.TEST_STRING.length; i++) {
  // String cipherText = RSACrypto.encrypt(Util.TEST_STRING[i]);
  // System.out.println("密文：");
  // System.out.println(cipherText);
  // String plainText = RSACrypto.decrypt(cipherText);
  // System.out.println("明文：");
  // System.out.println(plainText);
  // }
  // }
  //
  // // 此方法用于測試從Objective C傳遞的密文，OC加密所用公鑰為java生成，
  // // 解密所用密鑰為生成時保存在本地的密鑰。解密后返回明文
  // public static void testDecryptOCString() throws Exception {
  // uk = (RSAPublicKey) loadPublicKey(new File("C:\\javapublickey.pem"));
  // rk = (RSAPrivateKey) loadPrivateKey(new File("C:\\javaprivatekey.pem"));
  // String cipherText =
  // "ZTzhDS4nHg1KZ7rDSCoEtQjeWNeJZrJS4rI0im7c1eKUostV+Z6LMmf4HCk8Xsgs"
  // + "c4OLZ98iyIVeQWC5FtQLglxcg55vknbWVKziGziYSiNaUCJnKebNF4m2FTvuuhYs"
  // + "481kBGlM2dZIgxgSv3LI79NTUL4NCSS1dbyCtkYlTMs2eGW/sdrtlqgdHGBOQ0uV"
  // + "3ditg/ABY9vgmZIWg61xfmjRFatzuYt7nxobshr4+Sg7gz+z0tCwNJ0R7Y1PySnJ"
  // + "etXi1GM2jPMYGoERqlpDQaZ3Q4fzdmPt4iZvH+hPdETeJkXmgxHpEPdtVt36hYp3"
  // + "qj/JBprG9ZDMzBoFF5QttQ==";
  // byte[] cipherBytes = new BASE64Decoder().decodeBuffer(cipherText);
  // System.out.println("encrypted text:\n" + Util.byte2hex(cipherBytes));
  // String plainText = RSACrypto.decrypt(Util.byte2hex(cipherBytes));
  // System.out.println(plainText);
  // }
  //
  // // 測試用OC傳來的公鑰串加密文本，返回密文給OC用私鑰解密
  // // 公鑰可以從字符串載入，但私鑰無法載入
  // public static void testOCPublicKeyEncrypt() throws Exception {
  // // String strPublicKey =
  // //
  // "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArYO1yULWFbBF8DxC9Rw4AFg88Ft0EpgcSN4O9SWzXi5ktGUA2ZYp2HdKaWe/qV7G9fJU1W1vkueABtuy3zKeu2zbAzCd0d3hQtfxDlwEkU2AfxXXRnm8Oyv4EoWAqEe8d/EE7ocSotx+yLBsI2vrXddQrnVbpIKgvsPyewNVG0ppuRqQifNPQpAW3lmOUmz7j74qCV66zEgP5Ikvb4DcnZN+iu9KUKWOvwU90Sg/XHknBvBkVnm4l1NnWJ7MRR5qvFud0k883CrBHSHA9i0OC1NDMwveI5MXWNK/0UB9kE+cq6aXWus8YCAOuCxz88cyY1P3fiVfSco11wpuZLTLpQIDAQAB";
  // String strPublicKey =
  // "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArYO1yULWFbBF8DxC9Rw4"
  // + "AFg88Ft0EpgcSN4O9SWzXi5ktGUA2ZYp2HdKaWe/qV7G9fJU1W1vkueABtuy3zKe"
  // + "u2zbAzCd0d3hQtfxDlwEkU2AfxXXRnm8Oyv4EoWAqEe8d/EE7ocSotx+yLBsI2vr"
  // + "XddQrnVbpIKgvsPyewNVG0ppuRqQifNPQpAW3lmOUmz7j74qCV66zEgP5Ikvb4Dc"
  // + "nZN+iu9KUKWOvwU90Sg/XHknBvBkVnm4l1NnWJ7MRR5qvFud0k883CrBHSHA9i0O"
  // + "C1NDMwveI5MXWNK/0UB9kE+cq6aXWus8YCAOuCxz88cyY1P3fiVfSco11wpuZLTL"
  // + "pQIDAQAB";
  // // String strPrivateKey =
  // //
  // "MIIEowIBAAKCAQEArYO1yULWFbBF8DxC9Rw4AFg88Ft0EpgcSN4O9SWzXi5ktGUA2ZYp2HdKaWe/qV7G9fJU1W1vkueABtuy3zKeu2zbAzCd0d3hQtfxDlwEkU2AfxXXRnm8Oyv4EoWAqEe8d/EE7ocSotx+yLBsI2vrXddQrnVbpIKgvsPyewNVG0ppuRqQifNPQpAW3lmOUmz7j74qCV66zEgP5Ikvb4DcnZN+iu9KUKWOvwU90Sg/XHknBvBkVnm4l1NnWJ7MRR5qvFud0k883CrBHSHA9i0OC1NDMwveI5MXWNK/0UB9kE+cq6aXWus8YCAOuCxz88cyY1P3fiVfSco11wpuZLTLpQIDAQABAoIBACdHjbuF+djnEq4TtkSuoq7RStpOmbQr4xtLya8NXdGQRxPfWZXoPIjYWGwMJIM/BWNf/HxkTcG/zme/DHsihnR/bAUI2HFN/VSYdeV+RzpthQ0/8H/vxwDOL1ZiCoIN20h7s1YcFcfwinL8HT7Xi2yu9YDI6HoRaDpHOXlHg9itXDKKKkzynIc2HyJQr6JXjs5jwTYiLykzK6GowCl2vAmuuz2qMQBlLFG5u/0LjSHLiC31ZNxMNjhFrsHl8O0DKxUj/+A4wLdWzINTfBQS77eA3hsMnwB0stJ3qvlkbByNS44k9uS/e4hvlh3Dy03q/ted1M2L33fgS2l/YI889HECgYEA35hU506IULJlmSB1bQS/zNertJ8Nl0uoMXBNIMFHgcu0mUnEGe2kek/bTWR3sXXn3CLJNcRjd7MSrPSG1n46EQSCqRuJGpkNpNia8nxS0Tz13WYV2VCMc09a7CCiuKXX9MGasTN7xcfi8uTXEJfMNK54d/XvbZoaSgUfuIO5yD8CgYEAxqlTEjqS7qgjwXGx2VS7CTT02vto/2o4qvMofi5HEGhbvTciyprOD41/bU4fBRPD2eCswi2SyyIHUbFiqVHC3504mhXOMXH8z54MGNHNeOGuQ0qaDA2PqRcFtbdkCpxPnyiAdUZQ4clCT24diAyQ9hGt79co0AIaS5czWrnAExsCgYEA0xBQ1SfktYgxL6LcNdTN2OedRhr+EVtxoXmI1OqePX+1Mx3W50LUiEDpmtzDv9i0zbBoj0CbRFrdvjX1MnRlC7teO5OqkFj58Con2c5RvwH0dNHwvfqzGgZGpa8I65RhjsFS7QLUS5asPOyXtyoTsYcgYNze7m8Rcd30W5C8xrECgYBu4/lQxY1a1lQPGM2ziI5Wl07OJWP4nmw/UDecJ2zXhckfl3U+LqczG0Kz2tWJ2fyK09TbFuFHrhjzytZNuSvT8ki0CdPs2bnKkmgiOoo9HYxOV4ghjjhQpF81jcaz/YicSNlbnQJs5hCzkb2+QXVxRXEX3bwUT/gplZ6+18yVXQKBgF0W0NPAz1J+39kVsbRO9Vite0uf+btjE0NRo4Oh+wWYLQzkHC+ktLVjiDUef36E94BtlYhoRUYrFUDFq9gUIQPjtie3m+zY1eLLwaaC+tUBJy3TP8GHhgyWVqSXKVPEWa/5GKFpnoI4Y3LSA0D+Lm6qJejWfXjmhDuEFpm8ZDTI";
  // String strPrivateKey =
  // "MIIEowIBAAKCAQEArYO1yULWFbBF8DxC9Rw4AFg88Ft0EpgcSN4O9SWzXi5ktGUA"
  // + "2ZYp2HdKaWe/qV7G9fJU1W1vkueABtuy3zKeu2zbAzCd0d3hQtfxDlwEkU2AfxXX"
  // + "Rnm8Oyv4EoWAqEe8d/EE7ocSotx+yLBsI2vrXddQrnVbpIKgvsPyewNVG0ppuRqQ"
  // + "ifNPQpAW3lmOUmz7j74qCV66zEgP5Ikvb4DcnZN+iu9KUKWOvwU90Sg/XHknBvBk"
  // + "Vnm4l1NnWJ7MRR5qvFud0k883CrBHSHA9i0OC1NDMwveI5MXWNK/0UB9kE+cq6aX"
  // + "Wus8YCAOuCxz88cyY1P3fiVfSco11wpuZLTLpQIDAQABAoIBACdHjbuF+djnEq4T"
  // + "tkSuoq7RStpOmbQr4xtLya8NXdGQRxPfWZXoPIjYWGwMJIM/BWNf/HxkTcG/zme/"
  // + "DHsihnR/bAUI2HFN/VSYdeV+RzpthQ0/8H/vxwDOL1ZiCoIN20h7s1YcFcfwinL8"
  // + "HT7Xi2yu9YDI6HoRaDpHOXlHg9itXDKKKkzynIc2HyJQr6JXjs5jwTYiLykzK6Go"
  // + "wCl2vAmuuz2qMQBlLFG5u/0LjSHLiC31ZNxMNjhFrsHl8O0DKxUj/+A4wLdWzINT"
  // + "fBQS77eA3hsMnwB0stJ3qvlkbByNS44k9uS/e4hvlh3Dy03q/ted1M2L33fgS2l/"
  // + "YI889HECgYEA35hU506IULJlmSB1bQS/zNertJ8Nl0uoMXBNIMFHgcu0mUnEGe2k"
  // + "ek/bTWR3sXXn3CLJNcRjd7MSrPSG1n46EQSCqRuJGpkNpNia8nxS0Tz13WYV2VCM"
  // + "c09a7CCiuKXX9MGasTN7xcfi8uTXEJfMNK54d/XvbZoaSgUfuIO5yD8CgYEAxqlT"
  // + "EjqS7qgjwXGx2VS7CTT02vto/2o4qvMofi5HEGhbvTciyprOD41/bU4fBRPD2eCs"
  // + "wi2SyyIHUbFiqVHC3504mhXOMXH8z54MGNHNeOGuQ0qaDA2PqRcFtbdkCpxPnyiA"
  // + "dUZQ4clCT24diAyQ9hGt79co0AIaS5czWrnAExsCgYEA0xBQ1SfktYgxL6LcNdTN"
  // + "2OedRhr+EVtxoXmI1OqePX+1Mx3W50LUiEDpmtzDv9i0zbBoj0CbRFrdvjX1MnRl"
  // + "C7teO5OqkFj58Con2c5RvwH0dNHwvfqzGgZGpa8I65RhjsFS7QLUS5asPOyXtyoT"
  // + "sYcgYNze7m8Rcd30W5C8xrECgYBu4/lQxY1a1lQPGM2ziI5Wl07OJWP4nmw/UDec"
  // + "J2zXhckfl3U+LqczG0Kz2tWJ2fyK09TbFuFHrhjzytZNuSvT8ki0CdPs2bnKkmgi"
  // + "Ooo9HYxOV4ghjjhQpF81jcaz/YicSNlbnQJs5hCzkb2+QXVxRXEX3bwUT/gplZ6+"
  // + "18yVXQKBgF0W0NPAz1J+39kVsbRO9Vite0uf+btjE0NRo4Oh+wWYLQzkHC+ktLVj"
  // + "iDUef36E94BtlYhoRUYrFUDFq9gUIQPjtie3m+zY1eLLwaaC+tUBJy3TP8GHhgyW"
  // + "VqSXKVPEWa/5GKFpnoI4Y3LSA0D+Lm6qJejWfXjmhDuEFpm8ZDTI";
  // uk = (RSAPublicKey) getPublicKeyFromString(strPublicKey);
  // rk = (RSAPrivateKey) getPrivateKeyFromString(strPrivateKey);
  // for (int i = 0; i < Util.TEST_STRING.length; i++) {
  // String cipherText = RSACrypto.encrypt(Util.TEST_STRING[i]);
  // System.out.println("密文：");
  // System.out.println(cipherText);
  // String plainText = RSACrypto.decrypt(cipherText);
  // System.out.println("明文：");
  // System.out.println(plainText);
  // }
  // }
  //
  // // 測試用OC傳來的公鑰私鑰文件加密文本，返回密文給OC用私鑰解密
  // // 公鑰可以從文件載入，但私鑰無法載入
  // public static void testOCPublicKeyEncryptKeyFromFile() throws Exception {
  // uk = (RSAPublicKey) loadPublicKeyFromPEM("C:\\xml\\oc_public.pem");
  // rk = (RSAPrivateKey) loadPrivateKeyFromPEM("C:\\xml\\oc_private.pem");
  // for (int i = 0; i < Util.TEST_STRING.length; i++) {
  // String cipherText = RSACrypto.encrypt(Util.TEST_STRING[i]);
  // System.out.println("密文：");
  // System.out.println(cipherText);
  // String plainText = RSACrypto.decrypt(cipherText);
  // System.out.println("明文：");
  // System.out.println(plainText);
  // }
  // }
  //
  // // 測試用OC傳來的公鑰文件加密文本，返回密文給OC用私鑰解密
  // public static void testOCRTSAFileKeyEncrypt() throws Exception {
  // uk = (RSAPublicKey) loadPublicKeyFromPEM("C:\\xml\\public.pem");
  // rk = (RSAPrivateKey) loadPrivateKeyFromPEM("C:\\xml\\private.pem");
  // for (int i = 0; i < Util.TEST_STRING.length; i++) {
  // String cipherText = RSACrypto.encrypt(Util.TEST_STRING[i]);
  // System.out.println("密文：");
  // System.out.println(cipherText);
  // String plainText = RSACrypto.decrypt(cipherText);
  // System.out.println("明文：");
  // System.out.println(plainText);
  // }
  // }
  //
  // // 此方法用于測試從Objective C傳遞的密文，OC加密所用公鑰為java生成，
  // // 解密所用密鑰為生成時保存在本地的密鑰。解密后返回明文
  // // 公鑰和密鑰從字符串傳入
  // public static void testJavaDecryptOCStringKeyFromString() throws Exception
  // {
  // String strPublicKey =
  // "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0+YkVt/wfr9HpDupUXI8"
  // + "kQABmH2N40vToWZOddqic6cJEafbEyGGH4xK0EEdgS9oP5hYpUHpcditH+n1tIUq"
  // + "J/sQaeiAkKYoGKu7gVwhGhQZtXUcpVys6OONhorhn/cUsELJyl2OJMJ/8Z1cviCC"
  // + "ldmoQ3fatyb+hCQaQo4gV8uxCxrgPvyjFcxxBR0oFqN/dgvGejAZ7BBtskaq421O"
  // + "pBE4Y/EGYS5k3RMeh50VdL18kfFMUjihcUfk+6jgxiEzmwaa5aScmsSKHOyvIVAP"
  // + "VZbUE1Nq7AB3BHvD5FksVTdcrhNYTrDv+jALXW6r9ZvyzXfesxYGvZYJblOAYy+W"
  // + "HQIDAQA";
  // String strPrivateKey =
  // "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDT5iRW3/B+v0ek"
  // + "O6lRcjyRAAGYfY3jS9OhZk512qJzpwkRp9sTIYYfjErQQR2BL2g/mFilQelx2K0f"
  // + "6fW0hSon+xBp6ICQpigYq7uBXCEaFBm1dRylXKzo442GiuGf9xSwQsnKXY4kwn/x"
  // + "nVy+IIKV2ahDd9q3Jv6EJBpCjiBXy7ELGuA+/KMVzHEFHSgWo392C8Z6MBnsEG2y"
  // + "RqrjbU6kEThj8QZhLmTdEx6HnRV0vXyR8UxSOKFxR+T7qODGITObBprlpJyaxIoc"
  // + "7K8hUA9VltQTU2rsAHcEe8PkWSxVN1yuE1hOsO/6MAtdbqv1m/LNd96zFga9lglu"
  // + "U4BjL5YdAgMBAAECggEBAJ0gmi/FbRs/kctJ5lsbv6ex/nzqFU3Hy41yRJoF3tKt"
  // + "uP7bnorIICHCsTNOJafG1KHbwVgB0S53gqEYpvcOi90LwfcWzkb0vuTUa30YKP+i"
  // + "ihHRXsWMPDeRjT+IOpiY6kFttR6XUzEU/TTYAI6Hou2lca1d8dRAWRj5gHN72qXe"
  // + "bsbKd1fN8hvFd2Datit7Mi0XcU645x+Vq0xrhnD4HaXF2dtgGgpd++yYuEYVe9xN"
  // + "2Lqk2XrwySKi5Y2c9FZDI2WWxoeXSQUndo+DPfU5Vg7rDjDNnd2ZFaod6+j/7rwp"
  // + "HVsBPz8Z22RitTQkxpfeL5VBKTpNUfU5+nKdkc1weeECgYEA7zTD1YvvJzziUL2V"
  // + "MVe8vVrD/VZUk5f+k3NwLO6qEF1u7iaE9rB5wz8kDsq68h3YYV0d0HcSPRK5SY3c"
  // + "iyUDM4yfuW/2g+9YnbjkIh6tlN7VNJy18pO1l9hVmstYX1RmISOvZnx5Jhc4ORfC"
  // + "B2ZCkrn2ixR/xicwsyHLItVr6WUCgYEA4saWhKybzgbXc24gvwQ3+VPafgPP8mZ7"
  // + "WgbAmt+xmR1c/myh6tAmKA3EIn4GF1co7eEmKrIo4iLfX039Cnz01t0GlvXXeiM+"
  // + "+ts2pvpo+otQ5tEPKsZysJaOS2hI2Z/XyHQ5vNCIHBLiMaLeDmnOe1Gqr930spSC"
  // + "o260dHE/ilkCgYEAp0mmf4zalv1cZQ0A7r4mT+LPWDfs9D+DGYnM9I+Avesp7kFg"
  // + "Ecn/jc11oSaksTiwH/9oH2d2iOG0VT1x9JnQ8FczSROFOmXD+qHYYghEau2f+6hx"
  // + "EpG8mNIBpDz7s8epmRmEzE7Wxw3MExmLZ3NbsZN+WWvfpCu6Qjyq/NR3IIUCgYAK"
  // + "Q16QhpdOjbS2fqdwvaoi2I6s4VNJ7yVp/6A74h/RhCivQw9Y5y6y5VyZCwcPi1xI"
  // + "18W4bPO4uEdPsuHe1aTnDH2920ZzOqEhDUa969tQa3mv2IpNL0oFf+rUstWJM9i6"
  // + "M7hhOTbPvnMKOArAsD0uC5Yj+3GVm28GIn58PpvXkQKBgF/vOX0N4wt2kzq88wyV"
  // + "UF8yvMxPblOTJI67oSxrPWoHU00ksVq1J0KfFkPjEOk2XfVmGevF54bDqdjoRJgT"
  // + "fGuFWvqYFUrcR64IDZQOkzhxPUAnaKLcUj19+kh7/cR3iNiuIL08Fcuex3Wghonq"
  // + "QPnY2ByR77swJtG6lcINiaio";
  // uk = (RSAPublicKey) getPublicKeyFromString(strPublicKey);
  // rk = (RSAPrivateKey) getPrivateKeyFromString(strPrivateKey);
  // String[] arrEncrypted = new String[] {
  // "a8782c094d0f97724807b36a9ff7d354edcb4056f9bc9862bab7521c83b96aa4e242e7fcb5f45170d7f18ebd3b7f6e998638f3859b67160cab5a63fbfa2787748bc9e7d84b75f97d7abc5fff17f7aa99f5830e8d5ecef75efad7661bc34b9492e1e2f353286e22e868ccb4d8326629bd121027d58c3d8242f560f968798b9de4bbd80000e0c986988b45323fcbcde5b0c015f7389951040b811c18e56e4e931744df936f4db232cfc17b621daa20e98c6b7d644a32068ea44c3413403502a60d3e9650779f3ba7d9003ed60e4eb4188b13c4efd6e5965e397a7dc4f0cbdd1544c94acdcda5c15b7bcab9c381ce2d84711ef4758e896ecadead270daef003f879",
  // "1614e7635cf9bef69af4e31c96df09775733280abe07241988bec8238533255ef2daec411af919949d33d60d69c1a0895a13e5f0ccd16e312ba70e71bcb2ce3b89be8f50e752e5e2e3e12bf713cc6792ef9f4ee2429063337230a0aa0ee6695a4bd822998f5ef6a877e81970c0dc282a980df1293ad1cedac20f2fe4154597fcb73e95c0c0914df7d43169ad499e3b9cea8643168ba626a57bb5a2fa8d7b740777017d09832de1c87c1dc9b5cb639d82d6b852909eec932b2d703e5c715f98d486d300ea7cf0601d98e3760975ea99bd5977e44ac175ba10c0e5c986564368f66d57421bf8c2870f10dd5913a7ce1eff0d4592b708fb5181a9549dde52fe10e3",
  // "23eb4b98e247a852785fb0f671cbeda878c63d9c299f0b84c2746f389e65d0da92bf4e5edfb2fa45419041df9102dc4f88ad4bdfcd802b3f73e96db2054de2483615e9ba5c10430fa95a586dbca43b34c6104ea4abe40bcbc9c1bb14d75c309e7614e52c54e22e7d0f339714c7fb050c2ca611dc192f4a88c62f5b9bbc3a2df9376c33792d59338dc9929ca8c917b2acd163b31c7ffeb3d66a1812a1cc04830ff99eda20274a57e5175c389160d6e16038f832d415d2a63e6c0e314c6f91d9a62a6d30128a5d9340c88ebe0698ae6caff355d31791850a85f0741f54db812ffe48332d89d052eec9dabcd0ff4a70e2d4c21cd0534efbcdfca1bd3e33af172739",
  // "00e22ded50eed3ffe1c4dab0c66a4671bd52d1471ea182ca6ec97a30a7bc9211616795a67bf9c65294562bda45601fb3295c36bbae337aa14b55ff067097a23f02a177c622687a1941872045fe3e75c9fd0ede9a646506de55c1e3c43c05e2dd54c85efeaa00bf68341c17839e9898e5a4ba8ff51a0f68876adbeeb262e3760afdcd48a0113eccb031bacfa868d6d8569318d97a8b777223577ef9372bef9e4a119b3343d6a6e1da095bdd9259dbd6e1d0ac58dbb94a0e180ca25b0ba0576a297727ed46a80e04202d2ae56de5461974934b26b94a269cfe6426edd3f9c695f7bf8f54e6e87f3fab0dd58051b1d6162c9300085d73729e7405c7f67f434d899b",
  // "b4071fcbac44b111af10cc6f09f23b606423bc83cb5385234ac732274ca39981991cdbcc8392646f5113cf43df73c10b3ff073dc13ad86d09632b5da43aff1d569c1e665620989918a68723808fb9ade859b96d345bf78a5c7206ff85a494af92cba2ffd2688ec5f305c2b577f7be95cebb76191b1323fa5abff47bdfeeb2809fba692ef1007437db32538156a086a73006fd53f9b986f3f939708aace7bf136c20be40b4d0907a42bff235e90aec317bfa82527f2b2ac9f10d64f0ac984dfd7f3802ec54867cb30748e327fcecd7ad8900b76e49b3742f97c920593b78d00853a34afdb9a2c4a511530f39d913eb5e2c566de0e140cc72adbbf24e03ee01b52",
  // "b4af9bbcd97448f29da4cf479afca787a1f077af9a92fc08ab4fc334f87485f048f19bd448e3efeacff2472fa2ca4970eac14310a3286104f099638281cfe858e18cc4b6796184087806bd63376ea6ca0beb8c13ac43092bdfd207641b1bd9bf1e02be76983d2d27db49b1a507dae1a56d25953c81a29fd3c188939b0135bea04acdc7572f634674e7d7c940b7ec53d74786ab9394a9da5f60eb095a5899ae293bfbce7eb8215ead78a4dc2691506ac92e91d370165d92a076720b649e1190472a1c06ca08b075e7de8e25ed8e92c88a597e26f188f92ef0983a608a3a75249c66ebb87a479405ea8853db188b2beb9c1d786f5096e615da17d5e37bc4835e5a"
  // };
  //
  // for (int i = 0; i < arrEncrypted.length; i++) {
  // String plainText = RSACrypto.decrypt(arrEncrypted[i].toUpperCase());
  // System.out.println(plainText);
  // }
  // }
  //
  // // 此方法用于測試從Objective C傳遞的密文，OC加密所用公鑰為java生成，
  // // 解密所用密鑰為生成時保存在本地的密鑰。解密后返回明文
  // // 公鑰和密鑰從文件讀取
  // public static void testJavaDecryptOCStringKeyFromFile() throws Exception {
  // uk = (RSAPublicKey) loadPublicKeyFromPEM("C:\\public.pem");
  // rk = (RSAPrivateKey) loadPrivateKeyFromPEM("C:\\private.pem");
  // String[] arrEncrypted = new String[] {
  // "a8782c094d0f97724807b36a9ff7d354edcb4056f9bc9862bab7521c83b96aa4e242e7fcb5f45170d7f18ebd3b7f6e998638f3859b67160cab5a63fbfa2787748bc9e7d84b75f97d7abc5fff17f7aa99f5830e8d5ecef75efad7661bc34b9492e1e2f353286e22e868ccb4d8326629bd121027d58c3d8242f560f968798b9de4bbd80000e0c986988b45323fcbcde5b0c015f7389951040b811c18e56e4e931744df936f4db232cfc17b621daa20e98c6b7d644a32068ea44c3413403502a60d3e9650779f3ba7d9003ed60e4eb4188b13c4efd6e5965e397a7dc4f0cbdd1544c94acdcda5c15b7bcab9c381ce2d84711ef4758e896ecadead270daef003f879",
  // "1614e7635cf9bef69af4e31c96df09775733280abe07241988bec8238533255ef2daec411af919949d33d60d69c1a0895a13e5f0ccd16e312ba70e71bcb2ce3b89be8f50e752e5e2e3e12bf713cc6792ef9f4ee2429063337230a0aa0ee6695a4bd822998f5ef6a877e81970c0dc282a980df1293ad1cedac20f2fe4154597fcb73e95c0c0914df7d43169ad499e3b9cea8643168ba626a57bb5a2fa8d7b740777017d09832de1c87c1dc9b5cb639d82d6b852909eec932b2d703e5c715f98d486d300ea7cf0601d98e3760975ea99bd5977e44ac175ba10c0e5c986564368f66d57421bf8c2870f10dd5913a7ce1eff0d4592b708fb5181a9549dde52fe10e3",
  // "23eb4b98e247a852785fb0f671cbeda878c63d9c299f0b84c2746f389e65d0da92bf4e5edfb2fa45419041df9102dc4f88ad4bdfcd802b3f73e96db2054de2483615e9ba5c10430fa95a586dbca43b34c6104ea4abe40bcbc9c1bb14d75c309e7614e52c54e22e7d0f339714c7fb050c2ca611dc192f4a88c62f5b9bbc3a2df9376c33792d59338dc9929ca8c917b2acd163b31c7ffeb3d66a1812a1cc04830ff99eda20274a57e5175c389160d6e16038f832d415d2a63e6c0e314c6f91d9a62a6d30128a5d9340c88ebe0698ae6caff355d31791850a85f0741f54db812ffe48332d89d052eec9dabcd0ff4a70e2d4c21cd0534efbcdfca1bd3e33af172739",
  // "00e22ded50eed3ffe1c4dab0c66a4671bd52d1471ea182ca6ec97a30a7bc9211616795a67bf9c65294562bda45601fb3295c36bbae337aa14b55ff067097a23f02a177c622687a1941872045fe3e75c9fd0ede9a646506de55c1e3c43c05e2dd54c85efeaa00bf68341c17839e9898e5a4ba8ff51a0f68876adbeeb262e3760afdcd48a0113eccb031bacfa868d6d8569318d97a8b777223577ef9372bef9e4a119b3343d6a6e1da095bdd9259dbd6e1d0ac58dbb94a0e180ca25b0ba0576a297727ed46a80e04202d2ae56de5461974934b26b94a269cfe6426edd3f9c695f7bf8f54e6e87f3fab0dd58051b1d6162c9300085d73729e7405c7f67f434d899b",
  // "b4071fcbac44b111af10cc6f09f23b606423bc83cb5385234ac732274ca39981991cdbcc8392646f5113cf43df73c10b3ff073dc13ad86d09632b5da43aff1d569c1e665620989918a68723808fb9ade859b96d345bf78a5c7206ff85a494af92cba2ffd2688ec5f305c2b577f7be95cebb76191b1323fa5abff47bdfeeb2809fba692ef1007437db32538156a086a73006fd53f9b986f3f939708aace7bf136c20be40b4d0907a42bff235e90aec317bfa82527f2b2ac9f10d64f0ac984dfd7f3802ec54867cb30748e327fcecd7ad8900b76e49b3742f97c920593b78d00853a34afdb9a2c4a511530f39d913eb5e2c566de0e140cc72adbbf24e03ee01b52",
  // "b4af9bbcd97448f29da4cf479afca787a1f077af9a92fc08ab4fc334f87485f048f19bd448e3efeacff2472fa2ca4970eac14310a3286104f099638281cfe858e18cc4b6796184087806bd63376ea6ca0beb8c13ac43092bdfd207641b1bd9bf1e02be76983d2d27db49b1a507dae1a56d25953c81a29fd3c188939b0135bea04acdc7572f634674e7d7c940b7ec53d74786ab9394a9da5f60eb095a5899ae293bfbce7eb8215ead78a4dc2691506ac92e91d370165d92a076720b649e1190472a1c06ca08b075e7de8e25ed8e92c88a597e26f188f92ef0983a608a3a75249c66ebb87a479405ea8853db188b2beb9c1d786f5096e615da17d5e37bc4835e5a"
  // };
  //
  // for (int i = 0; i < arrEncrypted.length; i++) {
  // String plainText = RSACrypto.decrypt(arrEncrypted[i].toUpperCase());
  // System.out.println(plainText);
  // }
  // }
  //
  // // just for test
  // public static void main(String args[]) {
  // try {
  // // testGenerateAndSaveKey();
  // // testLoadKey();
  // // testGenerateAndSavePEM();
  // // testLoadPEM();
  // // testDecryptOCString();
  // // testOCPublicKeyEncrypt();
  // // testOCRTSAFileKeyEncrypt();
  // testOCPublicKeyEncryptKeyFromFile();
  // // testJavaDecryptOCStringKeyFromString();
  // // testJavaDecryptOCStringKeyFromFile();
  // }
  // catch (Exception e) {
  // e.printStackTrace();
  // }
  // }
}
